Unwinding instrumented program code

ABSTRACT

Method and apparatus for handling call stack unwinding when execution of an instrumented program is stopped in a first function of the instrumented program. When unwinding is initiated and a call to a second function of unwind software is made, the call to the second function is intercepted. The second function returns a reference to unwind information associated with the first function of the instrumented program. The unwind information includes references to locations of selected instructions in the function. If the first function of the instrumented program is instrumented with instrumentation code, then updated unwind information is created. The updated unwind information includes updated references to the locations of the selected instructions in the first function as offset by the instrumentation code. A reference to the updated unwind information is returned.

FIELD OF THE INVENTION

The present invention generally relates to instrumentation of computerprogram code, and more particularly to call-graph traversal, which isalso known as stack unwinding, in an instrumented program.

BACKGROUND

Analysis of binary executable programs is performed to analyze programperformance, verify correctness, and optimization, for example. Someanalyses are performed prior to runtime (static analysis), while otheranalyses are performed during runtime (dynamic analysis). For bothstatic and dynamic analysis, however, the analysis is often performed atthe function level.

The term, “function”, refers to named sections of code that are callablein the source program and encompasses routines, procedures, methods andother similar constructs known to those skilled in the art. Thefunctions in the source code are compiled into segments of executablecode. For convenience, the segments of executable code that correspondto the functions in the source code are also referred to as “functions”.

One category of analysis performed on executable programs is“instrumentation”. Instrumentation is generally used to gather runtimecharacteristics of a program. For example, the number of times that afunction is executed while the application is executing is determinedthrough instrumentation. While the information gathered throughinstrumentation may be extremely useful for purposes of enhancingprogram performance, the process of setting up a program forinstrumentation can be time-consuming and very complicated.

Some dynamic instrumentation tools relocate instrumented functionsduring execution of the program into a new address space, such as sharedmemory address space, on the stack of a target program, on the heap of atarget program or other similar methods. These different methods arereferenced in this description under the term “shared memory”. Theshared memory space is allocated by the instrumentation tool and sharedby the instrumentation tool and the executable program. The instrumentedfunctions in the shared memory space are executed in lieu of theun-instrumented versions of the functions in the original address space.Some instrumented functions in the shared memory space may call otherinstrumented functions in the shared memory space, depending on theapplication.

In certain situations the call graph (or the “call chain”) of a programmust be traversed. The call graph refers to the order in which functionsof the program are called and which of the functions are the calling andcalled functions. Traversal of the call graph is often referred to as“stack unwinding”. Stack unwinding allows identification of calling andcalled functions. For example, if foo1( ) calls foo2( ),foo2( ) callsfoo3( ), and foo3( ) calls foo4( ), stack unwinding from a location infoo4( ) allows identification of the chain of functions that were calledin getting to the location in foo4( ). Functions in the call graph canbe functions that have not been instrumented (“non-instrumentedfunctions”) or relocated instrumented functions.

An example situation in which stack unwinding is performed is when aprogram error occurs and a programmer is interested the function callingsequence relative to the location in the program at which the erroroccurred. This is sometimes referred to as a stack trace. Anotherexample is where a C++ exception is “thrown” in a C++ program. The C++runtime mechanism unwinds the stack upwards until it finds a matching“catch clause” (C++ terminology).

In some architectures, stack unwinding can be trivial. For example,where a single format is used for stack frames, traversing the callgraph is easily achieved by reading values from the stack of theapplication in a well-defined way. However, stack unwinding in otherarchitectures is more complicated because stack frames can havedifferent formats. For example, in the IA-64 processor architecture fromHewlett-Packard different formats of stack frames are used to optimizeperformance of a given code stream. Unwinding is performed by readingsupplemental unwind information that describes the format and content ofeach individual stack frame.

In the HP-UX system from Hewlett-Packard, the dynamic loader maintainsinformation that associates loaded modules and the locations of unwindinformation for the loaded modules. When unwinding is needed, forexample, because a C++ exception has been thrown, a function of thedynamic loader is called by the unwinder (libunwind on HP-UX) toidentify the unwind information of the load module and the functionwithin which the exception was raised. If unwinding is requested in aninstrumented function, e.g. a C++ exception is thrown in theinstrumented function, the dynamic loader will be unable to provide areference to the required unwind information because the dynamic loadermaintains only the unwind information for the un-instrumented version ofthe function. Unwinding through instrumented functions would thereforefail.

A system and method that address the aforementioned problems, as well asother related problems, are therefore desirable.

SUMMARY OF THE INVENTION

The present invention provides various methods and apparatus forhandling call stack unwinding when execution of an instrumented programis stopped in a first function of the instrumented program. Whenunwinding is initiated and a call to a second function of unwindsoftware is made, the call to the second function is intercepted. Thesecond function returns a reference to unwind information associatedwith the first function of the instrumented program. The unwindinformation includes references to locations of selected instructions inthe function. If the first function of the instrumented program isinstrumented with instrumentation code, then updated unwind informationis created. The updated unwind information includes updated referencesto the locations of the selected instructions in the first function asoffset by the instrumentation code. A reference to the updated unwindinformation is returned.

Various example embodiments are set forth in the Detailed Descriptionand Claims which follow.

BRIEF DESCRIPTION OF THE DRAWINGS

Various aspects and advantages of the invention will become apparentupon review of the following detailed description and upon reference tothe drawings in which:

FIG. 1 is a block diagram of executable code in which instrumentedversions of selected functions have been generated; and

FIG. 2 is a flowchart of a process for identifying unwind information inaccordance with one embodiment of the invention.

DETAILED DESCRIPTION

FIG. 1 is a block diagram of executable code in which instrumentedversions of selected functions have been generated. The executableprogram 202 includes original address space 204 and shared address space206, which is used for storage of relocated, instrumented functions. Inone embodiment, the process for allocating and mapping shared memory isimplemented consistent with the teachings of the patent applicationentitled, “DYNAMIC INSTRUMENTATION OF AN EXECUTABLE PROGRAM”, by Hundtet al., filed on Apr. 11, 2001, and having patent/application Ser. No.09/833,248, the contents of which are incorporated herein by reference.

Executable program 202 illustrates two functions, foo( ) 208 and bar( )210. Instrumented versions of foo( ) and bar( ) are created and aredesignated as foo′( ) 208′ and bar′( ) 210′ in shared address space 206.When an instrumented version of foo( ) is generated, probe code 212 isgenerated for foo′( ) in the shared address space 206. In addition, thefirst instruction of foo( ) 208 is replaced with an instruction tobranch to foo′( ).

In an example system (HP-UX), a load-module descriptor structure is usedto maintain pointers to unwind information for a loaded module. Thedynamic loader software maintains this information on HP-UX. Each loadedmodule has a dedicated load-module descriptor structure. The unwindersoftware needs the unwind information in order to perform stackunwinding, and the current instruction pointer (IP) value is used toidentify the proper load-module descriptor structure in the dynamicloader. Because each loaded module can be precisely correlated to anaddress range, the IP value will indicate the loaded module for a givenfunction and the proper location of unwind information.

If unwinding is initiated when the IP value is in an instrumentedfunction, however, the identity of the loaded module is not readilyapparent because instrumented functions are in shared address space 206,which is not associated with any one particular loaded module. Thus,requesting from the dynamic loader the identity of a load module for aninstrumented function will fail. In the HP-UX system, the dlmodinfofunction within the dynamic loader is typically called to obtain theidentity of the load module.

FIG. 2 is a flowchart of a process for identifying unwind information inaccordance with one embodiment of the invention. A first part of theprocess is activated when the unwinder library is loaded (step 252). Inone embodiment, the process for providing the appropriate unwindinformation for instrumented functions is implemented in an instrumenterprogram, such as the Caliper program from Hewlett-Packard. Theinstrumenter program attaches to the executable program, and the unwindlibrary is loaded when the program is started. A function pointer 258 iscreated (step 254) in shared memory 206, along with a breakpointfunction 260 (step 262). The function pointer references the breakpointfunction, which includes a breakpoint that transfers control to theinstrumenter program, followed by a return instruction.

The dynamic loader includes a function that provides access to theunwind information associated with the different loaded modules. Thefunction is referred to herein as dlmodinfo( ). A function of the unwindlibrary, get_dlmodinfo_fp( ), normally returns a pointer to dlmodinfo(). The function pointer is then used by the unwind library in subsequentoperations. In the example embodiment of the invention an instrumentedget_dlmodinfo_fp′( ) 264 of get_dlmodinfo_fp( ) is created (step 266) toreturn a function pointer to the breakpoint function instead of apointer to dlmodinfo( ). Thereafter in a second part of the process,each time unwinding is attempted, the breakpoint function is executed,which passes control to the instrumenter program. The instrumenterprovides the necessary unwind information for instrumented functions.

The second part of the process begins at step 268 and is initiated whenunwinding is attempted. The instrumented version (get_dlmodinfo_fp′( ))of get_dlmodinfo_fp( ) is invoked (step 268) and the function pointer tothe breakpoint function is returned. Upon return of the functionpointer, the breakpoint function is invoked (step 270). The executedbreakpoint in the breakpoint function causes control to be transferredto the instrumenter (step 272).

The instrumenter reads the parameters that would normally be provided inthe function call to dlmodinfo( ) (step 274). The parameters referencethe load-module descriptor structure. In one example processorarchitecture the parameters that are normally provided by the unwindersoftware to the dlmodinfo( ) function, are read from registers. It willbe appreciated that other processor architectures may specify differentlocations for parameters to functions. The parameters include thecurrent value of the instruction pointer (IP) and the location of theload-module descriptor structure to be filled with load moduleinformation by dlmodinfo( ).

If the IP value references an instrumented function (decision step 276),the unwind information for the IP value is recreated in a new location(step 278), and the load module descriptor structure is updated toreference the new unwind information. Whether the IP value references aninstrumented function is determined by comparing the IP value againstthe address ranges of load modules that have been loaded. In oneembodiment, the dynamic loader maintains these address ranges. In oneembodiment, the new unwind information (280) is stored in the sharedmemory that is accessible to the executable application and to theinstrumenter. Control is then returned to the instruction following thebreakpoint, which returns control to the unwinder software to continuewith unwinding the stack (step 282).

It will be appreciated that if the instrumented function is relocatedbut has no added instrumentation code, the original unwind informationwithin the load module address space is sufficient. An exampleembodiment addresses this case by updating the load module descriptorstructure with a pointer to this unwind information instead of creatingnew unwind information.

Where an instrumented function includes probe code, however, the newunwind information must be created because the unwind informationreferences particular instruction locations within the load module. Ifnew unwind information is not created, the instruction locations wouldnot be properly referenced. The following example illustrates unwindinformation containing references to instruction locations.

The unwind information for functions that exhibit a common code patternis compacted into a few bits in the IA-64 architecture. An instructionlocation is encoded as a slot index, t, relative to the beginning of thethe region of code, for example, the beginning of a function. The codebelow shows the first instructions of a function foo( ) in IA-64assembly language.

foo:: 0000 alloc r35 = ar.pfs, 0, 9, 2, 0 0000 mov r36 = rp 0000 adds r9= 0, sp 0010 addl r39 = 0, r1;; 0010 adds sp = −32, sp 0010 adds r37 =−16, r9 . . .The corresponding decoded unwind information is shown below. The linesof unwind information are numbered, and the numbers are referenced inthe description that follows.

1 R1prologue rlen = 6 2 P7rp_when t/spoff/pspoff = 1 3 P3rpgr gr/br = 364 P7pfs_when t/spoff/pspoff = 0 5 P3pfs_gr gr/br = 35 . . .Line 1 of the unwind information indicates to the unwind library thatthe code has a prologue region consisting of six instructions. Lines 2and 3 indicate that the return pointer is saved to general register r36in slot 1. Line 4 and 5 indicate that the ar.pfs register is saved togeneral register r35 in slot 0.

Thus, if as a result of instrumentation instructions are inserted at thebeginning of foo( ), the slot indices in the unwind information will notmatch the instrumented code. The unwind information that is recreated atstep 278 adjusts the slot indices and other values as needed to accountfor any code added during instrumentation.

If the IP value references a non-instrumented function, the pointers inthe load module descriptor structure are updated to reference the unwindinformation for the non-instrumented function. Control is then returnedto the instruction following the breakpoint, which returns control tothe unwinder software (step 282).

In addition to the example embodiments described above, other aspectsand embodiments of the present invention will be apparent to thoseskilled in the art from consideration of the specification and practiceof the invention disclosed herein. It is intended that the specificationand illustrated embodiments be considered as examples only, with a truescope and spirit of the invention being indicated by the followingclaims.

1. A computer-implemented method for handling call stack unwinding whenexecution of an instrumented program is stopped in a first function ofthe instrumented program, comprising: attaching an instrumenter programto the instrumented program; establishing a shared memory area for useby the instrumented program and the instrumenter program: creating abreakpoint function that includes a breakpoint that transfers control tothe instrumenter program; intercepting a call to a second function ofunwind software that returns a reference to unwind informationassociated with the first function of the instrumented program, theunwind information including references to locations of selectedinstructions in the function; creating an instrumented version of athird function of the unwind software, wherein the instrumented versionof the third function returns a function pointer to the breakpointfunction instead of returning a function pointer to the second function;if the first function of the instrumented program is instrumented withinstrumentation code, then creating updated unwind information thatincludes updated references to the locations of the selectedinstructions in the first function as offset by the instrumentation codeand returning a reference to the updated unwind information; storing theundated unwind information in the shared memory area; invoking theinstrumented version of the third function when the unwinding isinitiated; and executing the breakpoint function when the functionpointer to the breakpoint function is returned from the instrumentedversion of the third function.
 2. The method of claim 1, furthercomprising storing instrumented functions of the instrumented program inthe shared memory area.
 3. The method of claim 1, further comprisingstoring the breakpoint function and instrumented version of the thirdfunction in the shared memory area.
 4. The method of claim 1, furthercomprising: obtaining an instruction pointer value of the location inthe first function of the instrumented program at which execution wasstopped; and determining whether the first function of the instrumentedprogram is instrumented by reference to whether the instruction pointervalue is within address ranges of modules of the instrumented program.5. The method of claim 1, further comprising creating the breakpointfunction and the instrumented version of the third function upon loadingthe instrumented program.
 6. An apparatus for handling call stackunwinding when execution of an instrumented program is stopped in afirst function of the instrumented program, comprising: means forattaching an instrumenter program to the instrumented program; means forestablishing a shared memory area for use by the instrumented programand the instrumenter program; means for creating a breakpoint functionthat includes a breakpoint that transfers control to the instrumenterprogram; means for intercepting a call to a second function of unwindsoftware that returns a reference to unwind information associated withthe first function of the instrumented program, the unwind informationincluding references to locations of selected instructions in thefunction; means for creating an instrumented version of a third functionof the unwind software, wherein the instrumented version of the thirdfunction returns a function pointer to the breakpoint function insteadof returning a function pointer to the second function; means forcreating updated unwind information that includes updated references tothe locations of the selected instructions in the first function asoffset by the instrumentation code and returning a reference to theupdated unwind information, if the first function of the instrumentedprogram is instrumented with instrumentation code; means for storing theupdated unwind information in the shared memory area; means for invokingthe instrumented version of the third function when the unwinding isinitiated; and means for executing the breakpoint function when thefunction pointer to the breakpoint function is returned from theinstrumented version of the third function.